/****************************************************
          File Name:main.c
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Tue 13 Jan 2015 05:35:36 PM CST
*****************************************************/

#include "header.h"
#include "global.h"
#include "pisces_signal.h"
#include "pisces_process.h"
#include "pisces_log.h"
#include "pisces_readconf.h"
#include "pisces_socket.h"
#include <sys/resource.h>

static bool isdaemon = false;
pisces_ctx_t *ctx;

void exit_pisces(int sig)
{
    ctx->exit = 1;
    pisces_stop(ctx);
}

void re_new(int sig)
{
    pisces_wait_child();
    pisces_renew_workprocess(ctx);
}

void re_fresh(int sig)
{
    ctx->exit = 0;
    pisces_stop(ctx);
    pisces_readconf(ctx);
    int i;
    sleep(3);
    i = 0;
    close(ctx->listenfd);
 again:
    ctx->listenfd = pisces_socket(*ctx, NULL);
    if (ctx->listenfd == -1) {
        if (errno == EADDRINUSE) {
            sleep(3);
            if (i == 3) {
                pisces_log(P_LOG_ERR, "pisces_socket() %s", strerror(errno));
                exit(1);
            }
            i++;
            goto again;
        } else {
            pisces_log(P_LOG_ERR, "pisces_socket %s", strerror(errno));
            exit(EXIT_FAILURE);
        }
    }
    re_new(sig);
}

int main(int argc, char **argv)
{
    if (argc == 2)
        pisces_master_control(argv);

    struct rlimit lm;
    pid_t pppid;
    pisces_signal_t sig_chld, sig_hup, sig_trm;
    sigset_t old, block;

    sigemptyset(&old);
    sigemptyset(&block);
    sigaddset(&old, SIGCHLD);
    sigaddset(&old, SIGTERM);
    sigaddset(&old, SIGHUP);
    sigprocmask(SIG_SETMASK, &old, &block);

    ctx = (pisces_ctx_t *) malloc(sizeof(pisces_ctx_t));
    if (ctx == NULL) {
        fprintf(stderr, "Initialize context failed: %s\n", strerror(errno));
        exit(1);
    }

    getrlimit(RLIMIT_NPROC, &lm);
    lm.rlim_max = lm.rlim_cur + 1;
    setrlimit(RLIMIT_NPROC, &lm);

    if (pisces_open_log() == LOG_FAILED) {
        fprintf(stderr, "can't open log file, exiting...\n");
        exit(1);
    };

    if (!isdaemon) {
        if (my_daemon() == -1) {
            perror("Daemon");
            exit(EXIT_FAILURE);
        }
        isdaemon = true;
    }

    pppid = getpid();
    if (pisces_pidfile(&pppid, W_F) == -1) {
        pisces_log(P_LOG_ERR, "write pid file: %s", strerror(errno));
        exit(1);
    }

    if (pisces_readconf(ctx) == -1) {
        pisces_log(P_LOG_ERR, "can't read configuration file! %s", strerror(errno));
        exit(1);
    }

    chdir(ctx->conf->root_dir);

    sig_hup.signo = SIGHUP;
    sig_chld.signo = SIGCHLD;
    sig_trm.signo = SIGTERM;

    pisces_signal(&sig_hup, re_fresh);
    pisces_signal(&sig_chld, re_new);
    pisces_signal(&sig_trm, exit_pisces);

    ctx->listenfd = pisces_socket(*ctx, NULL);
    if (ctx->listenfd == -1) {
        pisces_log(P_LOG_ERR, "%s:%d pisces_socket %s", __FILE__, __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    pisces_get_workprocess_id(ctx);

    for (;;) {
        sigsuspend(&block);
        //pause();
    }
    pisces_log(P_LOG_ERR, "Fatal Error %s", strerror(errno));
    exit(EXIT_FAILURE);
}
